using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using SqEngine.Audio;
using sqengine.Engine.Common;
using SqEngine;
using TagLib;
using WMPLib;


namespace sqengine.Components
{
   
    public class MediaPlayerSystem : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private Game _game;
        private AudioManager _audiomanager;
        private string _songsdirectory;
        private SpriteBatch _spritebatch;
        private SpriteFont _mp_font;
        private AdvancedContent _adcontent;
        private SaveManager _saveman;

        private bool _israndomenabled = false;
        private bool _isscanning = false;
        private bool _finished = true;
        private bool _playing = false;
        private bool _paused = false;

        private Thread PopulateThread;

        private WindowsMediaPlayer wmp;
        private int _mp3count = 1;
        private int _mp3currentscan = 1;
        private string _mp3currentartist = "";
        private string _mp3currentsong_str;
        private MediaPlayerObject _mp3currentsong;
        private MediaPlayerObject _mp3prevsong;

        private int _mp3currentsong_idx = 0;


        private int bbWidth, bbHeight;


        private List<MediaPlayerObject> _mpfilelist = new List<MediaPlayerObject>();


        //Public events
        public bool IsScanning { get { return _isscanning; } }
        public bool IsRandomEnabled { get { return _israndomenabled; } }


        public void MediaPlayerControl(Actions action)
        {
            if (action == Actions.MediaPlayer_Play)
            {
                PlaySong(_israndomenabled);
            }

            if (action == Actions.MediaPlayer_Stop)
            {
                Stop();
            }


            if (action == Actions.MediaPlayer_Pause)
            {

                Pause();
            }
        }

        public void NextSong(bool state)
        {
            if (state)
            {
                Stop(false);
                PlaySong(_israndomenabled);

            }

        }

        public void BackSong(bool state)
        {
            if (state)
            {
                Stop(false);
                PlaySong(_mp3prevsong, _israndomenabled);

            }

        }

        


        public void EnabledRandom(bool state)
        {
            if (state)
            {
                _israndomenabled = !_israndomenabled;

                ((sqengine)_game).AddMessage(String.Format("Random enabled: {0}", _israndomenabled), Color.Blue, 3000, "Textures/UI/MediaPlayer/random" + _israndomenabled.ToString());
            }
        }

        public void RandomEnabled(bool state)
        {
            _israndomenabled = state;
            ((sqengine)_game).AddMessage(String.Format("Random enabled: {0}", _israndomenabled), Color.Blue, 3000, "Textures/UI/MediaPlayer/random" + _israndomenabled.ToString());

        }
        private void PlaySong(bool random)
        {
            PlaySong(null, random);
        }

        private void PlaySong(MediaPlayerObject mediaplobj, bool random)
        {
            if (_mpfilelist.Count > 0)
            {
                if (!_playing)
                {
                    if (mediaplobj == null)
                    {
                        mediaplobj = GetNextSong(random);

                    }
                    else
                    {
                        _mp3prevsong = mediaplobj;

                    }

                    wmp.URL = mediaplobj.Filename;
                    ((sqengine)_game).AddMessage(String.Format("{0}\n{1} [{2}]", mediaplobj.Artist, mediaplobj.SongName, wmp.currentMedia.durationString), Color.Blue, 3000, "Textures/UI/MediaPlayer/play");
                    wmp.controls.play();

                    _playing = true;
                }
                else
                    if (_paused)
                    {
                        Resume();
                    }
            }
        }

        private void Stop(bool showmsg)
        {
            if (_playing)
            {
                wmp.controls.stop();
                _playing = false;
                if (showmsg)

                ((sqengine)_game).AddMessage("Stopped", Color.Blue, 3000, "Textures/UI/MediaPlayer/stop");


            }

        }

        public void Stop()
        {
            Stop(false);

        }

        private void Resume()
        {
            if (_paused)
            {

                wmp.controls.play();
                _playing = true;
                _paused = false;
                ((sqengine)_game).AddMessage("Resumed", Color.Blue, 3000, "Textures/UI/MediaPlayer/play");
            }

        }

        private void Pause()
        {
            if (_playing)
            {
                wmp.controls.pause();
                _playing = false;
                _paused = true;
                ((sqengine)_game).AddMessage("Pause", Color.Blue, 3000, "Textures/UI/MediaPlayer/pause");

            }

        }

        private MediaPlayerObject GetNextSong(bool random)
        {

            if (random)
            {
                Random rnd = new Random();
                _mp3currentsong_idx = rnd.Next(_mp3count);

            }
            else
            {
                _mp3currentsong_idx++;

            }


            _mp3currentsong = _mpfilelist[_mp3currentsong_idx];

            return _mp3currentsong;

        }

        public MediaPlayerSystem(Game game, AudioManager audiomanager, string songsdirectory, AdvancedContent adcontent, SaveManager saveman)
            : base(game)
        {
            _game = game;
            _saveman = saveman;
            _audiomanager = audiomanager;
            _adcontent = adcontent;
            _songsdirectory = songsdirectory;

            wmp = new WindowsMediaPlayer();

            PrepareThread();

            if (System.IO.File.Exists(_adcontent.ContentRoot + "/Config/sqplaylist.pll"))
            {
                MediaPlayerPlaylist mpo = new MediaPlayerPlaylist();

                mpo = saveman.LoadMediaPlayerPlaylist(_adcontent.ContentRoot + "/Config/sqplaylist.pll");
                _mpfilelist = mpo.MP3List;
                _mp3count = mpo.MP3Count;
                _songsdirectory = mpo.Directory;
            }



        }

        public override void Initialize()
        {
            base.Initialize();
        }



        public void PrepareThread()
        {

            PopulateThread = new Thread(new ThreadStart(PopulateMP3List));
            PopulateThread.Name = "Populate mp3 list";
            PopulateThread.Priority = ThreadPriority.Normal;

        }
        protected override void UnloadContent()
        {
            if (PopulateThread != null &&
                    PopulateThread.IsAlive)
            {
                PopulateThread.Abort();
            }

            wmp.controls.stop();
            wmp.close();

            base.UnloadContent();

        }

        public override void Update(GameTime gameTime)
        {
            if (_finished && _songsdirectory != "")
            {
                _finished = false;

                ((sqengine)_game).AddMessage(String.Format("{0} MP3 loaded!!", _mp3count), Color.Blue, 3000, "Textures/UI/MediaPlayer/volume");
                MediaPlayerPlaylist mpl = new MediaPlayerPlaylist();

                mpl.MP3List = _mpfilelist;
                mpl.MP3Count = _mp3count;
                mpl.Directory = _songsdirectory;
                mpl.SaveTime = DateTime.Now;

                if (System.IO.File.Exists(_adcontent.ContentRoot + "/Config/sqplaylist.pll"))
                    System.IO.File.Delete(_adcontent.ContentRoot + "/Config/sqplaylist.pll");

                _saveman.SaveMediaPlayerPlaylist(_adcontent.ContentRoot + "/Config/sqplaylist.pll", mpl);

            }
            if (_playing)
            {
                if (wmp.controls.currentPosition == wmp.controls.currentItem.duration)
                {
                    Stop();
                    PlaySong(_israndomenabled);
                }

            }
            base.Update(gameTime);
        }

        private void GraphicsDevice_DeviceReset(object sender, EventArgs e)
        {
            bbWidth = GraphicsDevice.PresentationParameters.BackBufferWidth;
            bbHeight = GraphicsDevice.PresentationParameters.BackBufferHeight;
        }

        protected override void LoadContent()
        {
            this.GraphicsDevice.DeviceReset += new EventHandler(GraphicsDevice_DeviceReset);
            GraphicsDevice_DeviceReset(null, null);


        }


        public override void Draw(GameTime gameTime)
        {
            if (_spritebatch == null)
                _spritebatch = new SpriteBatch(_game.GraphicsDevice);

            if (_mp_font == null)
                _mp_font = _adcontent.LoadSpriteFont("Fonts/Console");

            _spritebatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);

            //Stop Populating progress
            if (PopulateThread != null && PopulateThread.IsAlive)
            {
                string loading_str = String.Format("Loading mp3: {0}%\n{1} - {2} ", GetPercentage(_mp3currentscan, _mp3count, 2), _mp3currentartist, _mp3currentsong_str);

                try
                {
                    _spritebatch.DrawString(_mp_font, loading_str, new Vector2(bbWidth - 400, 50), Color.White);
                    _spritebatch.DrawString(_mp_font, loading_str, new Vector2(bbWidth - 399, 51), Color.Black);
                }
                catch
                {

                }
            }

            if (_playing)
            {

                string playing_str = String.Format("Playing {0}-{1}", wmp.controls.currentPositionString, wmp.currentMedia.durationString);
                float met = (bbWidth / 2) - (_mp_font.MeasureString(playing_str).X / 2);

                _spritebatch.DrawString(_mp_font, playing_str, new Vector2(met - 1, 30), Color.White);
                _spritebatch.DrawString(_mp_font, playing_str, new Vector2(met, 31), Color.Blue);

            }

            _spritebatch.End();
            base.Draw(gameTime);
        }

        public void Populate(string directory)
        {
            if (PopulateThread == null)
                PrepareThread();

            if (!PopulateThread.IsAlive)
            {
                _songsdirectory = directory;
                PopulateThread.Start();
            }
        }

        public void Populate()
        {
            Populate(_songsdirectory);
        }

        public void Play()
        {
            PlaySong(_israndomenabled);

        }


        private void PopulateMP3List()
        {
            if (_songsdirectory != "")
            {
                List<string> result = Functions.GetFilesRecursive(_songsdirectory, "*.mp3");
                MediaPlayerObject mpo = new MediaPlayerObject();

                _mp3count = result.Count;
                _isscanning = true;

                foreach (string mp3 in result)
                {
                    mpo = new MediaPlayerObject();
                    try
                    {
                        TagLib.File tagmp3 = TagLib.File.Create(mp3);

                        mpo.Filename = mp3;
                        mpo.Duration = tagmp3.Properties.Duration.TotalMilliseconds;

                        mpo.SongName = tagmp3.Tag.Title;
                        mpo.Album = tagmp3.Tag.Album;
                        mpo.Artist = tagmp3.Tag.FirstPerformer;

                        _mp3currentartist = mpo.Artist;
                        _mp3currentsong_str = mpo.SongName;

                        _mpfilelist.Add(mpo);

                        _mp3currentscan++;

                    }
                    catch
                    {

                    }
                }

                PopulateThread = null;
                _isscanning = false;
                _finished = true;
            }

        }

        /// <summary>
        /// Generates a percentage, formatted with "places" decimal places.
        /// </summary>
        /// <param name="value">Value for which a percentage is needed</param>
        /// <param name="total">Total of all values from which to generate a percentage</param>
        /// <param name="places">How many decimal places to return in the percentage string</param>
        /// <returns>string with the percentage value</returns>
        public static string GetPercentage(int value, int total, int places)
        {
            Decimal percent = 0;
            string retval = string.Empty;
            String strplaces = new String('0', places);

            if (value == null) value = 0;
            if (total == null) total = 0;

            if (value == 0 || total == 0)
            {
                percent = 0;
            }
            else
            {
                percent = Decimal.Divide(value, total) * 100;

                if (places > 0)
                {
                    strplaces = "." + strplaces;
                }
            }

            retval = percent.ToString("#" + strplaces);
            return retval;
        }
     
    }
}